package fr.auzaiphe.admin.bdd;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class BaseDeDonnee
{
	private String nomFichierASauvegarder;
	private Connection connexion;
	private String jdbcDriver = "org.hsqldb.jdbcDriver";
	private String database = "jdbc:hsqldb:file:temp/bdd";
	private String user = "sa";
	private String password = "";


	/**
	 * Initialisation du nom de fichier
	 */
	public BaseDeDonnee()
	{
		this.nomFichierASauvegarder = new String();
	}

	/**
	 * Change le nom du fichier vers lequel on sauvegardera
	 * @param nomFichier
	 */
	public void changerNomFichier(String nomFichier)
	{
		this.nomFichierASauvegarder = nomFichier;
	}

	/**
	 * Supprime le dossier temporaire de la base de donn�e
	 * et coupe proprement la connexion � la base
	 */
	public void supprimerBDD()
	{
		this.arretDB();
		this.supprimerFichier(new File("temp"));
	}

	/**
	 * Permet de supprimer un dossier
	 * @param path
	 * @return Boolean pour indiquer si le dossier est bien supprimé
	 */
	public boolean supprimerFichier(File path)
	{
        boolean resultat = true;

        if( path.exists() )
        {
			File[] files = path.listFiles();
			for(int i=0; i<files.length; i++)
			{
				if(files[i].isDirectory())
				{
					resultat &= this.supprimerFichier(files[i]);
				}
				else
				{
					resultat &= files[i].delete();
				}
			}
        }
        resultat &= path.delete();

        return resultat;
	}

	/**
	 * Fait la copie d'un fichier
	 * Utile lors de la sauvegarde ou on passera les données du fichier
	 * temp au fichier de sauvegarde
	 * @param inFichier
	 * @param outFichier
	 */
	public void dupliquerFichier(String inFichier, String outFichier)
	{
		FileChannel in = null; // canal d'entr�e
		FileChannel out = null; // canal de sortie

		try
		{
			// Init
			in = new FileInputStream(inFichier).getChannel();
			out = new FileOutputStream(outFichier).getChannel();

			// Copie depuis le in vers le out
			in.transferTo(0, in.size(), out);
		}
		catch (Exception e)
		{
			// Toute exception pouvant arriver
			e.printStackTrace();
		}
		finally
		{
			// Quelque soit l'issu de la copie on ferme les fichiers
			if(in != null)
			{
				try
				{
					in.close();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}

			if( out != null )
			{
				try
				{
			  		out.close();
			  	}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * Ouvre une base de donnée avec le nom
	 * temp
	 * @param nomFichier
	 */
	public void nouveau()
	{
		this.supprimerFichier(new File("temp"));
		new File("temp").mkdir();
		this.nomFichierASauvegarder = "";
		this.connexionDB();
		this.initialiserBase();
	}

	/**
	 * Ouvre un fichier .murder
	 * passé en paramètre
	 * @param nomFichier
	 */
	public void ouvrir(String nomFichier)
	{
		this.arretDB();
		this.supprimerFichier(new File("temp"));
		this.nomFichierASauvegarder = nomFichier;
		new File("temp").mkdir();
		this.dupliquerFichier(nomFichier, "temp/bdd.script");
		this.connexionDB();
	}

	/**
	 * Enregistre le fichier avec le nom pr�cis� dans l'attribut
	 * nomFichierASauvegarder
	 * On arrete la BDD pour pr�server les donn�es
	 * @throws SQLException
	 */
	public void enregister()
	{
		this.arretDB();
		//Ajout de l'extention '.murder'
		if(!this.nomFichierASauvegarder.matches(".*.murder"))
			this.nomFichierASauvegarder = this.nomFichierASauvegarder.concat(".murder");
		this.dupliquerFichier( "temp/bdd.script", this.nomFichierASauvegarder );
		this.connexionDB();
	}

	/**
	 * Initialise la BDD
	 * Lit ligne par ligne le script de création de la base et les executes
	 * @throws SQLException
	 */
	public void initialiserBase()
	{
		String requete = "";

		try
		{
			InputStream ips = this.getClass().getResourceAsStream( "/script.sql" );
			InputStreamReader ipsr=new InputStreamReader(ips);
			BufferedReader br=new BufferedReader(ipsr);
			String ligne;
			while ( ( ligne=br.readLine() ) != null )
			{
				requete = requete + ligne;
			}
			br.close();
		}
		catch (Exception e)
		{
		        System.out.println( e.toString() );
		}
		try
		{
			this.executerUpdate( requete );
			//initialisation, ne peut pas �tre fait a partir du scenario
			this.executerUpdate("INSERT INTO SCENARIO( SCENARIO_ID,SCENARIO_CHRONO,SCENARIO_TEXTE) VALUES ('1','0','');");
			//this.executerUpdate("INSERT INTO ALERTE( JOUEUR_ID,ALERTE_HEURE_AFFICHE,ALERTE_TEXTE,ALERTE_LIEN_FICHIER) VALUES ('1','100','texte','lienFichier');");

		} catch (SQLException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Ouvre une connexion à la base de donn�e
	 * Instancie le JDBC + lance la connexion
	 */
	public void connexionDB()
	{
		try
		{
			Class.forName(this.jdbcDriver).newInstance();
		}
		catch (InstantiationException e)
		{
			System.out.println("ERROR: failed to load HSQLDB JDBC driver.");
			e.printStackTrace();
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}

		try
		{
			this.connexion = DriverManager.getConnection(this.database, this.user, this.password);
		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * Arréte correctement HSQLDB,
	 * Deconnecte l'application de la base de donn�e
	 * @throws SQLException
	 */
	public void arretDB()
	{
		Statement st;
		try
		{
			st = this.connexion.createStatement();
			// arrete proprement HSQLDB
			st.execute("SHUTDOWN");
			// ferme la connexion
			this.connexion.close();
		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * Execute la requete passée en param�tre
	 *
	 * @param requete String contenant la requete SQL
	 * @throws SQLException
	 */
	public void executerUpdate(String requete) throws SQLException
	{
		System.out.println(requete);
		/*
		PreparedStatement statement = this.connexion.prepareStatement(requete);
		statement.executeUpdate();
		statement.close();
		/*/
		//*

		//requete.replace("'", "\'");
		//requete.replace('"','\"');

		//requete= "LOL";
		//requete = requete.replace("'", "\\'");
		//requete = requete.replace("'", "\\\\'");

		Statement statement;
		statement = this.connexion.createStatement();
		statement.executeUpdate(requete);
		//*/
	}

	/**
	 * Execute la requete passée en param�tre
	 *
	 * @param requete contient la requ�te SQL
	 * @throws SQLException
	 */
	public ResultSet executerRequete(String requete) throws SQLException
	{
		System.out.println(requete);
		//*

		//requete=requete.replaceAll("'","\'");
		//requete=requete.replaceAll('"','\"');

		//requete = requete.replace("'", "\\'");
		//requete = requete.replace("'", "\\\\'");

		Statement statement;
		statement = this.connexion.createStatement();
		//*/
		/*
		PreparedStatement statement = this.connexion.prepareStatement(requete);
		//*/
		ResultSet resultat = statement.executeQuery(requete);
		statement.close();
		return resultat;
	}

	public String getNomFichierASauvegarder()
	{
		return this.nomFichierASauvegarder;
	}

}
